using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using PortfolioAllocator.Optimization;

namespace PortfolioAllocator.GUI
{
    public partial class PortfolioAllocatorWindow : Form
    {
        #region Private Members
        public static readonly string LOADER_COL = "Loader";
        public static readonly string TICKER_COL = "Ticker";
        public static readonly string EXP_RET_COL = "Exp(R)";
        public static readonly string MIN_WEIGHT_COL = "Min W";
        public static readonly string MAX_WEIGHT_COL = "Max W";

        public static readonly string FORMAT_EXT_PROPERTY = "Format";
        static private readonly TraceSwitch traceM = new TraceSwitch("PortfolioAllocatorWindow", "Debug info for PortfolioAllocator GUI class");

        private DataTable constituentsM;
        private List<OptimizationRunner.PConstraint> constraintsM = new List<OptimizationRunner.PConstraint>();
        #endregion

        public PortfolioAllocatorWindow()
        {
            InitializeComponent();

            // Create empty DataTable with correct columns
            this.constituentsM = new DataTable();
            this.constituentsM.Columns.Add(LOADER_COL, typeof(TALoaders.Loader));
            this.constituentsM.Columns.Add(TICKER_COL, typeof(string));
            this.constituentsM.Columns.Add(EXP_RET_COL, typeof(double)).ExtendedProperties.Add(FORMAT_EXT_PROPERTY, "P2");
            this.constituentsM.Columns.Add(MIN_WEIGHT_COL, typeof(double)).ExtendedProperties.Add(FORMAT_EXT_PROPERTY, "P2");
            this.constituentsM.Columns.Add(MAX_WEIGHT_COL, typeof(double)).ExtendedProperties.Add(FORMAT_EXT_PROPERTY, "P2");
            // Assign DataTable ot the dataGridView
            this.dgViewConstituentsM.DataSource = this.constituentsM;
            // Format DataGridView Columns
            for (int ix = 0; ix < this.constituentsM.Columns.Count; ++ix)
            {
                DataGridViewColumn col = this.dgViewConstituentsM.Columns[ix];
                if (this.constituentsM.Columns[ix].ExtendedProperties.ContainsKey(PortfolioAllocatorWindow.FORMAT_EXT_PROPERTY))
                    col.DefaultCellStyle.Format = (string)this.constituentsM.Columns[ix].ExtendedProperties[PortfolioAllocatorWindow.FORMAT_EXT_PROPERTY];
            }
        }

        /// <summary>Save input DataTable into CSV file</summary>
        private void btSaveConstM_Click(object sender, EventArgs e)
        {
            Debug.WriteLine(traceM.TraceInfo, "save constituents called...");

            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".csv";
            dlg.Filter = "Constituents files (*.csv)|*.csv";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string fileName = dlg.FileName;
                TALoaders.Utilities.saveDataTableToCSV(fileName, this.constituentsM);
                Debug.WriteLineIf(traceM.TraceInfo, " saved to " + fileName);
            }
            else
                Debug.WriteLineIf(traceM.TraceInfo, " NOT SAVED!!");
        }
        /// <summary>Load input DataTable from a CSV file</summary>
        private void btLoadConstM_Click(object sender, EventArgs e)
        {
            Debug.WriteLine(traceM.TraceInfo, "load constituents called...");
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.DefaultExt = ".csv";
            dlg.Filter = "Constituents files (*.csv)|*.csv";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string fileName = dlg.FileName;
                this.constituentsM.Clear();
                TALoaders.Utilities.loadCSVToDataTable(fileName, ref this.constituentsM);
                Debug.WriteLineIf(traceM.TraceInfo, " opened from " + fileName);
            }
            else
                Debug.WriteLineIf(traceM.TraceInfo, " NOT LOADED!!");
        }

        // Run optimization
        private void btOptimizeM_Click(object sender, EventArgs e)
        {
            DateTime startDate = this.dtStartDateM.Value.Date;
            DateTime endDate = this.dtEndDateM.Value.Date;
            Optimization.OptimizationRunner runner = new Optimization.OptimizationRunner();

            if (this.rbMinVarianceM.Checked)
            {
                DataTable optResult = runner.runMinVarianceAnalysis(this.constituentsM, startDate, endDate, this.constraintsM);
                AllocationResult resultForm = new AllocationResult(optResult, AllocationResult.ResultType.Allocation);
                resultForm.Show();
            }
            else if (this.rbBackTestM.Checked)
            {
                DataTable btResult = runner.runMinVarBackTest(this.constituentsM, startDate, endDate, this.constraintsM);
                AllocationResult resultForm = new AllocationResult(btResult, AllocationResult.ResultType.BackTest);
                resultForm.Show();
            }
                
        }

        private void btAddConstraintM_Click(object sender, EventArgs e)
        {
            List<string> tickers = new List<string>();
            for(int rowIx = 0; rowIx < this.dgViewConstituentsM.Rows.Count; ++rowIx)
            {
                DataGridViewRow row = this.dgViewConstituentsM.Rows[rowIx];
                if (row.Selected)
                    tickers.Add((string)this.constituentsM.Rows[rowIx][TICKER_COL]);
            }
            double min = Convert.ToDouble(this.tbMinM.Text);
            double max = Convert.ToDouble(this.tbMaxM.Text);
            OptimizationRunner.PConstraint constr = new OptimizationRunner.PConstraint(min, max, tickers);
            this.constraintsM.Add(constr);

            StringBuilder sb = new StringBuilder(this.rbConstraintsM.Text);
            sb.Append(min + " <= ");
            for (int i = 0; i < tickers.Count; ++i)
            {
                if (i > 0)
                    sb.Append(" + ");
                sb.Append(tickers[i]);
            }
            sb.AppendLine(" <= " + max);
            this.rbConstraintsM.Text = sb.ToString();
        }

    }
}